#ifndef G3_QUATERNIONS_H
#define G3_QUATERNIONS_H

// Thanks to Cal3D
// Thanks to Bruno 'Beosil' Heidelberger

#include "log.h"

#include "m_vector.h"
#include "m_matrix.h"

namespace G3 {

enum AXIS_ID {
	GAXIS_Y = 0,
	GAXIS_X = 1,
	GAXIS_Z = 2
};

class QUATERNIONF {
public:
    QUATERNIONF (float X = 0.0f, float Y = 0.0f, float Z = 0.0f, float W = 1.0f);
    QUATERNIONF (VEC3F Rot);

    float x, y, z, w;

//==============================================================================
// Calculate the value of W from X, Y and Z
//==============================================================================
    void CalcW ();

//==============================================================================
// Creates a quaternion from axis and angle
//==============================================================================
    void CreateFromAxisAngle (float Angle, VEC3F Axis);

//==============================================================================
// Calculates axis and angle from the quaternion
//==============================================================================
    void GetAxisAngle (float *Angle, VEC3F *Axis);
	float GetAngle (AXIS_ID AxisID);

//==============================================================================
// Converts quaternion into a matrix
//==============================================================================
    MATRIX4x4F GetMatrix ();

    QUATERNIONF& operator=(const QUATERNIONF &q);

//==============================================================================
// Multiplies quaternions
//==============================================================================
    QUATERNIONF operator*(const QUATERNIONF &q) const;

//==============================================================================
// Applies the quaternion to a vector
//==============================================================================
    QUATERNIONF operator*(const VEC3F &v) const;

//==============================================================================
// Gets the length of quaternion
//==============================================================================
    float GetLength ();

//==============================================================================
// Normalizes the quaternion
//==============================================================================
    void Normalize ();

//==============================================================================
// Conjugates the quaternion
//==============================================================================
    void Conjugate ();

//==============================================================================
// Inverts the quaternion
//==============================================================================
    void Invert ();
};

//==============================================================================
// Experimental version of CreateFromAxisAngle
//==============================================================================
QUATERNIONF Euler2Quat (VEC3F Angle);

//==============================================================================
// Conjugates a quaternion
//==============================================================================
QUATERNIONF Conjugate (QUATERNIONF q);

//==============================================================================
// Applies a quaternion to a vector
//==============================================================================
VEC3F ApplyQuat (VEC3F v, QUATERNIONF q);

//==============================================================================
// Dot product of two quaternions
//==============================================================================
float DotProduct (const QUATERNIONF &q1, const QUATERNIONF &q2);

//==============================================================================
// Spherical linear interpolation between quaternions
//==============================================================================
QUATERNIONF Slerp (const QUATERNIONF &a, const QUATERNIONF &b, float factor);

}

#endif //G3_QUATERNIONS_H
